home *** CD-ROM | disk | FTP | other *** search
/ Amiga Tools 2 / Amiga Tools 2.iso / tools / vim / src / archie.c < prev    next >
C/C++ Source or Header  |  1995-03-09  |  13KB  |  763 lines

  1. /* vi:ts=4:sw=4
  2.  *
  3.  *
  4.  * VIM - Vi IMproved
  5.  *
  6.  * Code Contributions By:    Bram Moolenaar            mool@oce.nl
  7.  *                            Tim Thompson            twitch!tjt
  8.  *                            Tony Andrews            onecom!wldrdg!tony 
  9.  *                            G. R. (Fred) Walter        watmath!watcgl!grwalter 
  10.  */
  11. /*
  12.  * archie.c -- RISC OS + UnixLib specific code.
  13.  *
  14.  * A lot of this file was written by Juergen Weigert.
  15.  *
  16.  * It was then hacked to pieces by Alun Jones to work on the Acorn
  17.  * Archimedes!
  18.  */
  19.  
  20. #include "vim.h"
  21. #include "globals.h"
  22. #include "param.h"
  23. #include "proto.h"
  24.  
  25. #include <fcntl.h>
  26. #include <time.h>
  27. #include <unistd.h>
  28. #include <sys/types.h>
  29. #include <sys/os.h>
  30. #include <signal.h>
  31.  
  32. #include <termio.h>
  33.  
  34. static int    Read __ARGS((char *, long));
  35. static int    WaitForChar __ARGS((int));
  36. static int    RealWaitForChar __ARGS((int));
  37. static void fill_inbuf __ARGS((void));
  38.  
  39. static int do_resize = FALSE;
  40.  
  41. /* I'm sure this should be defined in UnixLib, but it ain't!
  42.  */
  43. short ospeed;
  44.  
  45.     void
  46. mch_write(s, len)
  47.     char    *s;
  48.     int        len;
  49. {
  50.     int i;
  51.     for (i=0; i<len; i++)
  52.     {
  53.         os_vdu(s[i]);
  54.     }
  55. }
  56.  
  57. /*
  58.  * GetChars(): low level input funcion.
  59.  * Get a characters from the keyboard.
  60.  * If time == 0 do not wait for characters.
  61.  * If time == n wait a short time for characters.
  62.  * If time == -1 wait forever for characters.
  63.  */
  64.     int
  65. GetChars(buf, maxlen, time)
  66.     char    *buf;
  67.     int        maxlen;
  68.     int        time;
  69. {
  70.     if (time >= 0)
  71.     {
  72.         if (WaitForChar(time) == 0)        /* no character available */
  73.             return 0;
  74.     }
  75.     else        /* time == -1 */
  76.     {
  77.     /*
  78.      * If there is no character available within 2 seconds (default)
  79.      * write the autoscript file to disk
  80.      */
  81.         if (WaitForChar((int)p_ut) == 0)
  82.             updatescript(0);
  83.     }
  84.  
  85.     WaitForChar(-1);
  86.     return Read(buf, (long)maxlen);
  87. }
  88.  
  89.     void
  90. vim_delay()
  91. {
  92.     clock_t    now;
  93.  
  94.     now = clock();
  95.     while (clock() < now + CLOCKS_PER_SEC/2);
  96. }
  97.  
  98. /*
  99.  * No job control. Fake it by starting a new shell.
  100.  */
  101.     void
  102. mch_suspend()
  103. {
  104.     outstr("new shell started\n");
  105.     call_shell(NULL, 0, 1);
  106. }
  107.  
  108.     void
  109. mch_windinit()
  110. {
  111.     Columns = 80;
  112.     Rows = 24;
  113.  
  114.     flushbuf();
  115.  
  116.     mch_get_winsize();
  117. }
  118.  
  119. /*
  120.  * Check_win checks whether we have an interactive window.
  121.  */
  122.  
  123.     void
  124. check_win(argc, argv)
  125.     int argc;
  126.     char **argv;
  127. {
  128.     if (!isatty(0) || !isatty(1))
  129.     {
  130.         fprintf(stderr, "VIM: no controlling terminal\n");
  131.         exit(2);
  132.     }
  133. }
  134.  
  135. /*
  136.  * fname_case(): Set the case of the filename, if it already exists.
  137.  *                 This will cause the filename to remain exactly the same.
  138.  */
  139.     void
  140. fname_case(name)
  141.     char *name;
  142. {
  143. }
  144.  
  145.     void
  146. settitle(str)
  147.     char *str;
  148. {
  149. }
  150.  
  151.     void
  152. resettitle()
  153. {
  154. }
  155.  
  156. /*
  157.  * Get name of current directory into buffer 'buf' of length 'len' bytes.
  158.  * Return non-zero for success.
  159.  */
  160.     int 
  161. dirname(buf, len)
  162.     char *buf;
  163.     int len;
  164. {
  165.     extern int        errno;
  166.     extern char        *sys_errlist[];
  167.  
  168.     if (getcwd(buf,len) == NULL)
  169.     {
  170.         strcpy(buf, sys_errlist[errno]);
  171.         return 0;
  172.     }
  173.     return 1;
  174. }
  175.  
  176. /*
  177.  * get absolute filename into buffer 'buf' of length 'len' bytes
  178.  */
  179.     int 
  180. FullName(fname, buf, len)
  181.     char *fname, *buf;
  182.     int len;
  183. {
  184.     int        l;
  185.     char    olddir[MAXPATHL];
  186.     char    *p;
  187.     int        c;
  188.     int        retval = 1;
  189.  
  190.     if (fname == NULL)    /* always fail */
  191.         return 0;
  192.  
  193.     *buf = 0;
  194.     if (*fname != '/')
  195.     {
  196.         /*
  197.          * If the file name has a path, change to that directory for a moment,
  198.          * and then do the getwd() (and get back to where we were).
  199.          * This will get the correct path name with "../" things.
  200.          */
  201.         if ((p = strrchr(fname, '/')) != NULL)
  202.         {
  203.             if (getcwd(olddir, MAXPATHL) == NULL)
  204.             {
  205.                 p = NULL;        /* can't get current dir: don't chdir */
  206.                 retval = 0;
  207.             }
  208.             else
  209.             {
  210.                 c = *p;
  211.                 *p = NUL;
  212.                 chdir("\\");        /* Try to maintain PSD */
  213.                 if (chdir(fname))
  214.                     retval = 0;
  215.                 else
  216.                     fname = p + 1;
  217.                 *p = c;
  218.             }
  219.         }
  220.         if (getcwd(buf, len) == NULL)
  221.         {
  222.             retval = 0;
  223.             *buf = NUL;
  224.         }
  225.         l = strlen(buf);
  226.         if (l && buf[l - 1] != '/')
  227.             strcat(buf, "/");
  228.         if (p)
  229.         {
  230.             chdir("\\");            /* Maintain PSD */
  231.             chdir(olddir);
  232.         }
  233.     }
  234.     strcat(buf, fname);
  235.     return retval;
  236. }
  237.  
  238. /*
  239.  * get file permissions for 'name'
  240.  */
  241.     long 
  242. getperm(name)
  243.     char *name;
  244. {
  245.     struct stat statb;
  246.  
  247.     if (stat(name, &statb))
  248.         return -1;
  249.     return statb.st_mode;
  250. }
  251.  
  252. /*
  253.  * set file permission for 'name' to 'perm'
  254.  */
  255.     int
  256. setperm(name, perm)
  257.     char *name;
  258.     int perm;
  259. {
  260.     return chmod(name, perm);
  261. }
  262.  
  263. /*
  264.  * check if "name" is a directory
  265.  */
  266.     int 
  267. isdir(name)
  268.     char *name;
  269. {
  270.     struct stat statb;
  271.  
  272.     if (stat(name, &statb))
  273.         return -1;
  274.     return (statb.st_mode & S_IFMT) == S_IFDIR;
  275. }
  276.  
  277.     void
  278. mch_windexit(r)
  279.     int r;
  280. {
  281.     settmode(0);
  282.     stoptermcap();
  283.     flushbuf();
  284.     stopscript();                    /* remove autoscript file */
  285.     exit(r);
  286. }
  287.  
  288.     void
  289. mch_settmode(raw)
  290.     int                raw;
  291. {
  292.     static    int old225, old226, old4;
  293.     int        retvals[3];
  294.     static struct termio told;
  295.            struct termio tnew;
  296.  
  297.     if (raw)
  298.     {
  299.         /* Make arrow keys act as function keys.
  300.          */
  301.         os_byte(4, 2, 0, retvals);
  302.         old4 = retvals[1];
  303.         /* Now make function keys return NULL followed by a character.
  304.          * Remember the old value for resetting.
  305.          */
  306.         os_byte(225, 0xC0, 0, retvals);
  307.         old225 = retvals[1];
  308.         os_byte(226, 0xD0, 0, retvals);
  309.         old226 = retvals[1];
  310.  
  311.         ioctl(0, TCGETA, &told);
  312.         tnew = told;
  313.         tnew.c_iflag &= ~(ICRNL | IXON);        /* ICRNL enables typing ^V^M */
  314.                                                 /* IXON enables typing ^S/^Q */
  315.         tnew.c_lflag &= ~(ICANON | ECHO | ISIG | ECHOE);
  316.         tnew.c_cc[VMIN] = 1;            /* return after 1 char */
  317.         tnew.c_cc[VTIME] = 0;            /* don't wait */
  318.         ioctl(0, TCSETA, &tnew);
  319.     }
  320.     else
  321.     {
  322.         os_byte(4, old4, 0, retvals);
  323.         os_byte(225, old225, 0, retvals);
  324.         os_byte(226, old226, 0, retvals);
  325.         ioctl(0, TCSETA, &told);
  326.     }
  327. }
  328.  
  329. /*
  330.  * Try to get the current window size:
  331.  * 1. with an ioctl(), most accurate method
  332.  * 2. from the environment variables LINES and COLUMNS
  333.  * 3. from the termcap
  334.  * 4. keep using the old values
  335.  */
  336.     int
  337. mch_get_winsize()
  338. {
  339.     int            old_Rows = Rows;
  340.     int            old_Columns = Columns;
  341.     char        *p;
  342.  
  343.     Columns = 0;
  344.     Rows = 0;
  345.  
  346. /*
  347.  * 1. try using an ioctl. It is the most accurate method.
  348.  */
  349.     {
  350.         struct winsize    ws;
  351.  
  352.         if (ioctl(0, TIOCGWINSZ, &ws) == 0)
  353.         {
  354.             Columns = ws.ws_col;
  355.             Rows = ws.ws_row;
  356.         }
  357.     }
  358.  
  359. /*
  360.  * 2. get size from environment
  361.  */
  362.     if (Columns == 0 || Rows == 0)
  363.     {
  364.         if ((p = (char *)getenv("LINES")))
  365.             Rows = atoi(p);
  366.         if ((p = (char *)getenv("COLUMNS")))
  367.             Columns = atoi(p);
  368.     }
  369.  
  370. /*
  371.  * 3. try reading the termcap
  372.  */
  373.     if (Columns == 0 || Rows == 0)
  374.     {
  375.         extern void getlinecol();
  376.  
  377.         getlinecol();    /* get "co" and "li" entries from termcap */
  378.     }
  379.  
  380. /*
  381.  * 4. If everything fails, use the old values
  382.  */
  383.     if (Columns <= 0 || Rows <= 0)
  384.     {
  385.         Columns = old_Columns;
  386.         Rows = old_Rows;
  387.         return 1;
  388.     }
  389.     debug2("mch_get_winsize: %dx%d\n", (int)Columns, (int)Rows);
  390.  
  391.     Rows_max = Rows;                /* remember physical max height */
  392.  
  393.     check_winsize();
  394.     script_winsize();
  395.  
  396. /* if size changed: screenalloc will allocate new screen buffers */
  397.     return (0);
  398. }
  399.  
  400.     void
  401. mch_set_winsize()
  402. {
  403.     /* should try to set the window size to Rows and Columns */
  404. }
  405.  
  406.     int 
  407. call_shell(cmd, dummy, cooked)
  408.     char    *cmd;
  409.     int        dummy;
  410.     int        cooked;
  411. {
  412.     int        x;
  413.     char    newcmd[1024];
  414.  
  415.     flushbuf();
  416.  
  417.     if (cooked)
  418.         settmode(0);                 /* set to cooked mode */
  419.  
  420.     if (cmd == NULL)
  421.         x = system(p_sh);
  422.     else
  423.     {
  424.         sprintf(newcmd, "*%s", cmd);
  425.         x = system(newcmd);
  426.     }
  427.     if (x == 127)
  428.     {
  429.         emsg("Cannot execute shell sh");
  430.         outchar('\n');
  431.     }
  432.     else if (x)
  433.     {
  434.         smsg("%d returned", x);
  435.         outchar('\n');
  436.     }
  437.  
  438.     if (cooked)
  439.         settmode(1);                         /* set to raw mode */
  440.     return x;
  441.  
  442. }
  443.  
  444. /*
  445.  * The input characters are buffered to be able to check for a CTRL-C.
  446.  * This should be done with signals, but I don't know how to do that in
  447.  * a portable way for a tty in RAW mode.
  448.  */
  449.  
  450. #define INBUFLEN 50
  451. static unsigned char        inbuf[INBUFLEN];    /* internal typeahead buffer */
  452. static int                    inbufcount = 0;        /* number of chars in inbuf[] */
  453.  
  454.     static int
  455. Read(buf, maxlen)
  456.     char    *buf;
  457.     long    maxlen;
  458. {
  459.     if (inbufcount == 0)        /* if the buffer is empty, fill it */
  460.         fill_inbuf();
  461.     if (maxlen > inbufcount)
  462.         maxlen = inbufcount;
  463.     memmove(buf, inbuf, maxlen);
  464.     inbufcount -= maxlen;
  465.     if (inbufcount)
  466.         memmove(inbuf, inbuf + maxlen, inbufcount);
  467.     return (int)maxlen;
  468. }
  469.  
  470.     void
  471. breakcheck()
  472. {
  473. /*
  474.  * check for CTRL-C typed by reading all available characters
  475.  */
  476.     if (RealWaitForChar(0))        /* if characters available */
  477.         fill_inbuf();
  478. }
  479.  
  480.     static void
  481. fill_inbuf()
  482. {
  483.     int        len;
  484.  
  485.     if (inbufcount >= INBUFLEN)        /* buffer full */
  486.         return;
  487.  
  488.     for (len=0; len < INBUFLEN-inbufcount; len++)
  489.     {
  490.         int key;
  491.  
  492.         key = os_inkey(0);
  493.         if (key==-1)
  494.         {
  495.             break;
  496.         }
  497.         inbuf[inbufcount+len] = key;
  498.     }
  499.  
  500.     while (len-- > 0)
  501.     {
  502.         /*
  503.          * if a CTRL-C was typed, remove it from the buffer and set got_int
  504.          */
  505.         if (inbuf[inbufcount] == 3)
  506.         {
  507.             /* remove everything typed before the CTRL-C */
  508.             memmove(inbuf, inbuf + inbufcount, len + 1);
  509.             inbufcount = 0;
  510.             got_int = TRUE;
  511.         }
  512.         ++inbufcount;
  513.     }
  514. }
  515.  
  516. /* 
  517.  * Wait "ticks" until a character is available from the keyboard or from inbuf[]
  518.  * ticks = -1 will block forever
  519.  */
  520.  
  521.     static int
  522. WaitForChar(ticks)
  523.     int ticks;
  524. {
  525.     if (inbufcount)        /* something in inbuf[] */
  526.         return 1;
  527.     return RealWaitForChar(ticks);
  528. }
  529.  
  530. /* 
  531.  * Wait "ticks" until a character is available from the keyboard
  532.  * ticks = -1 will block forever
  533.  */
  534.     static int
  535. RealWaitForChar(ticks)
  536.     int ticks;
  537. {
  538.     int    key;
  539.  
  540.     if (ticks == -1)
  541.     {
  542.         key = os_get();
  543.     }
  544.     else
  545.     {
  546.         key = os_inkey(ticks/10);
  547.     }
  548. debug3("RWFC(%d) got %d (%c)\n", ticks, key, key);
  549.     
  550.     if (key != -1)
  551.     {
  552.         /* Unfortunately the key has now been taken from the
  553.          * buffer, so we need to put it in outselves. It's a 
  554.          * shame, but the other way I can think of involves a
  555.          * keyboard scan, and this would return for SHIFT, etc.
  556.          */
  557.          if (inbufcount < INBUFLEN)
  558.          {
  559.              inbuf[inbufcount++] = key;
  560.         }
  561.     }
  562.     return (key != -1);
  563. }
  564.  
  565. /*
  566.  * ExpandWildCard() - this code does wild-card pattern matching using the shell
  567.  *
  568.  * Mool: return 0 for success, 1 for error (you may loose some memory) and
  569.  *       put an error message in *file.
  570.  *
  571.  * num_pat is number of input patterns
  572.  * pat is array of pointers to input patterns
  573.  * num_file is pointer to number of matched file names
  574.  * file is pointer to array of pointers to matched file names
  575.  * On Unix we do not check for files only yet
  576.  * list_notfound is ignored
  577.  */
  578.  
  579. extern char *mktemp __ARGS((char *));
  580. #ifndef SEEK_SET
  581. # define SEEK_SET 0
  582. #endif
  583. #ifndef SEEK_END
  584. # define SEEK_END 2
  585. #endif
  586.  
  587.     int
  588. ExpandWildCards(num_pat, pat, num_file, file, files_only, list_notfound)
  589.     int             num_pat;
  590.     char          **pat;
  591.     int            *num_file;
  592.     char         ***file;
  593.     int                files_only;
  594.     int                list_notfound;
  595. {
  596.     char    tmpname[TMPNAMELEN];
  597.     char    *command;
  598.     int        i;
  599.     int        dir;
  600.     size_t    len;
  601.     FILE    *fd;
  602.     char    *buffer;
  603.     char    *p;
  604.  
  605.     *num_file = 0;        /* default: no files found */
  606.     *file = (char **)"";
  607.  
  608.     /*
  609.      * If there are no wildcards, just copy the names to allocated memory.
  610.      * Saves a lot of time, because we don't have to run glob.
  611.      */
  612.     if (!have_wildcard(num_pat, pat))
  613.     {
  614.         *file = (char **)alloc(num_pat * sizeof(char *));
  615.         if (*file == NULL)
  616.         {
  617.             *file = (char **)"";
  618.             return 1;
  619.         }
  620.         for (i = 0; i < num_pat; i++)
  621.             (*file)[i] = strsave(pat[i]);
  622.         *num_file = num_pat;
  623.         return 0;
  624.     }
  625.  
  626. /*
  627.  * get a name for the temp file
  628.  */
  629.     strcpy(tmpname, TMPNAME2);
  630.     if (*mktemp(tmpname) == NUL)
  631.     {
  632.         emsg(e_notmp);
  633.         return 1;
  634.     }
  635.  
  636.     len = TMPNAMELEN + 10;
  637.     for (i = 0; i < num_pat; ++i)        /* count the length of the patterns */
  638.         len += strlen(pat[i]) + 1;
  639.     command = (char *)alloc(len);
  640.     if (command == NULL)
  641.         return 1;
  642.     strcpy(command, "glob >");            /* built the shell command */
  643.     strcat(command, tmpname);
  644.     for (i = 0; i < num_pat; ++i)
  645.     {
  646.         strcat(command, " ");
  647.         strcat(command, pat[i]);
  648.     }
  649.     i = call_shell(command, 0, FALSE);        /* execute it */
  650.     free(command);
  651.     if (i)                                    /* call_shell failed */
  652.     {
  653.         remove(tmpname);
  654.         sleep(1);            /* give the user a chance to read error messages */
  655.         must_redraw = CLEAR;                /* probably messed up screen */
  656.         return 1;
  657.     }
  658.  
  659. /*
  660.  * read the names from the file into memory
  661.  */
  662.      fd = fopen(tmpname, "r");
  663.     if (fd == NULL)
  664.     {
  665.         emsg(e_notopen);
  666.         return 1;
  667.     }
  668.  
  669.     fseek(fd, 0L, SEEK_END);
  670.     len = ftell(fd);                /* get size of temp file */
  671.     fseek(fd, 0L, SEEK_SET);
  672.     buffer = (char *)alloc(len + 1);
  673.     if (buffer == NULL)
  674.     {
  675.         remove(tmpname);
  676.         fclose(fd);
  677.         return 1;
  678.     }
  679.     i = fread(buffer, 1, len, fd);
  680.     fclose(fd);
  681.     remove(tmpname);
  682.     if (i != len)
  683.     {
  684.         emsg(e_notread);
  685.         free(buffer);
  686.         return 1;
  687.     }
  688.  
  689.     buffer[len] = NUL;                    /* make sure the buffers ends in NUL */
  690.     i = 0;
  691.     for (p = buffer; p < buffer + len; ++p)
  692.         if (*p == NUL)                    /* count entry */
  693.             ++i;
  694.     if (len)
  695.         ++i;                            /* count last entry */
  696.  
  697.     *num_file = i;
  698.     *file = (char **)alloc(sizeof(char *) * i);
  699.     if (*file == NULL)
  700.     {
  701.         free(buffer);
  702.         *file = (char **)"";
  703.         return 1;
  704.     }
  705.     p = buffer;
  706.  
  707.     for (i = 0; i < *num_file; ++i)
  708.     {
  709.         (*file)[i] = p;
  710.         while (*p && p < buffer + len)        /* skip entry */
  711.             ++p;
  712.         ++p;                                /* skip NUL */
  713.     }
  714.     for (i = 0; i < *num_file; ++i)
  715.     {
  716.         dir = (isdir((*file)[i]) > 0);
  717.         if (dir < 0)            /* if file doesn't exist don't add '.' */
  718.             dir = 0;
  719.         p = alloc((unsigned)(strlen((*file)[i]) + 1 + dir));
  720.         if (p)
  721.         {
  722.             strcpy(p, (*file)[i]);
  723.             if (dir)
  724.                 strcat(p, ".");
  725.         }
  726.         (*file)[i] = p;
  727.     }
  728.     free(buffer);
  729.     return 0;
  730. }
  731.  
  732.     void
  733. FreeWild(num, file)
  734.     int        num;
  735.     char    **file;
  736. {
  737.     if (file == NULL || num == 0)
  738.         return;
  739.     while (num--)
  740.         free(file[num]);
  741.     free(file);
  742. }
  743.  
  744.     int
  745. has_wildcard(p)
  746.     char *p;
  747. {
  748.     return strpbrk(p, "*#") != NULL;
  749. }
  750.  
  751.     int
  752. have_wildcard(num, file)
  753.     int        num;
  754.     char    **file;
  755. {
  756.     register int i;
  757.  
  758.     for (i = 0; i < num; i++)
  759.         if (has_wildcard(file[i]))
  760.             return 1;
  761.     return 0;
  762. }
  763.